import React from 'react';
import src from './source';
import * as FieldUtil from './fieldUtil';
import * as DetailUtil from './detailUtil';
import * as _ from './common';
import { formatDate } from './formatUtil'
import './e8Interface';
import { toJS } from 'mobx';
import * as AI from './analyzeData';
const jQuery = window.jQuery;

jQuery.fn.extend({
    bindPropertyChange: function(funobj){
        return this.each(function () {
            var thisid = jQuery(this).attr('id');
            window.WfForm.addPropertyChangeFn(thisid, funobj);
        });
    }
});

const WfForm_Public = {
    isMobile: function(){
        return src.isMobile;
    },
    __propertyChangeFnObj: {},
    __detailFieldChangeFnObj: {},
    getGlobalStore: function(){
        return src.globalStore;
    },
    getLayoutStore: function(){
    	return src.layoutStore;
    },
    getBaseInfo: function(){
        return src.globalStore.baseParam;
    },
    getFnaConfig: function(){
        return src.layoutStore.fnaInfo;
    },
    getOdocConfig:function(){
        return src.layoutStore.odocInfo;
    },
    addPropertyChangeFn: function(key, funobj){
        if(!key || key.indexOf("field") === -1)
            return;
        let fnArr = this.__propertyChangeFnObj[key];
        if (!!!fnArr) {
            fnArr = new Array();
            this.__propertyChangeFnObj[key] = fnArr;
        }
        fnArr.push(funobj);
    },
    /**
     * 控制表单按钮是否点击
     * @param flag : true 按钮全部置灰不可操作 false 恢复按钮可操作状态
     */
    controlBtnDisabled: function(isDisabled){
        src.globalStore.setApiBtnDisabled(isDisabled);
    },
    judgeIsLoading: function(){
        return src.globalStore.btnDisabled;
    },
    /**
     * 字段值变化绑定事件
     * @params fieldMark(String) 绑定字段标示串，明细字段带下划线标示
     */
    bindFieldChangeEvent: function(fieldMarkStr, funobj){
        !!fieldMarkStr && fieldMarkStr.split(",").map(fieldMark =>{
            this.addPropertyChangeFn(fieldMark, funobj);
        });
    },
    /**
     * 明细字段值变化绑定事件，绑定后对新添加的行也生效
     * @params fieldMark(String) 绑定的明细字段标示串，不带下划线标示
     */
    bindDetailFieldChangeEvent: function(fieldMarkStr, funobj){
        const reg = /^field\d+$/;
        !!fieldMarkStr && fieldMarkStr.split(",").map(key =>{
            if(!key || !reg.test(key))
                return "";
            let fnArr = this.__detailFieldChangeFnObj[key];
            if (!!!fnArr) {
                fnArr = new Array();
                this.__detailFieldChangeFnObj[key] = fnArr;
            }
            fnArr.push(funobj);
        });
    },
    customTabFunObj:{},
    bindCustomTabEvnent:function(key,fun){
        this.customTabFunObj[key] = fun;
    },
    /**
     * 触发开发代码绑定的字段值变更事件，layoutStore中调用
     */
    triggerFieldBindEvent: function(fieldMark, newValue){
        if(fieldMark in this.__propertyChangeFnObj){
            this.__propertyChangeFnObj[fieldMark].map(fn =>{
                try{
                    fn(jQuery("#"+fieldMark)[0], fieldMark, newValue);
                }catch(e){}
            });
        }
        const index = fieldMark.indexOf("_");
        const fieldid = index>-1 ? fieldMark.substring(5, index) : fieldMark.substring(5);
        const rowIndex = index>-1 ? fieldMark.substring(index+1) : -1;
        const fieldAttr = this.getFieldInfo(fieldid);
        if(fieldAttr.isDetail){   //明细字段触发监听事件
            if(`field${fieldid}` in this.__detailFieldChangeFnObj){
                this.__detailFieldChangeFnObj[`field${fieldid}`].map(fn =>{
                    try{
                        fn(`field${fieldid}`, rowIndex, newValue);
                    }catch(e){}
                });
            }
        }
    },
    /**
     * 字段名称转换为字段id
     * @param symbol  主表/明细表标示，main/detail_1/detail_2，默认为main
     * @param prefix 是否需要field字符串前缀，默认为true
     */
    convertFieldNameToId: function(fieldname, symbol, prefix){
        symbol = !!symbol ? symbol : "main";
        prefix = typeof prefix === "undefined" ? true : prefix;
        const { fieldNameMap } = src.layoutStore;
        const fieldKey = `${symbol}.${fieldname.toUpperCase()}`;
        let fieldid = "";
        if(fieldNameMap.has(fieldKey)){
            fieldid = fieldNameMap.get(fieldKey)
            fieldid = prefix ? `field${fieldid}` : fieldid;
        }
        return fieldid;
    },
    /**
     * 获取字段信息
     */
    getFieldInfo: function(fieldid){
        fieldid = fieldid.toString();
        const { fieldAttrMap } = src.layoutStore;
        return fieldAttrMap.has(fieldid) ? toJS(fieldAttrMap.get(fieldid)) : {};
    },
    /**
     * 获取字段当前的字段属性
     */
    getFieldCurViewAttr: function(fieldMark){
        return FieldUtil.getFieldCurViewAttr(fieldMark);
    },
    /**
     * 获取字段值
     * @params fieldMark(String)    字段标示,主表字段：field110，明细行字段需加上行标示：field110_4
     */
    getFieldValue: function(fieldMark){
        const fieldObj = this.getFieldObj(fieldMark);
        return fieldObj === null ? "" : fieldObj.value;
    },
    /**
     * 获取字段值对象
     */
    getFieldValueObj: function(fieldMark){
        const fieldObj = this.getFieldObj(fieldMark);
        return fieldObj === null ? {} : fieldObj.valueObj;
    },
    getFieldObj: function(fieldMark){
        if(fieldMark.indexOf("field") === -1)
            return null;
        const index = fieldMark.indexOf("_");
        const fieldid = index>-1 ? fieldMark.substring(5, index) : fieldMark.substring(5);
        const rowIndex = index>-1 ? fieldMark.substring(index+1) : -1;
        return FieldUtil.getFieldValObj(fieldid, rowIndex);
    },
    /**
     * 获取选择框字段对应的显示值
     */
    getSelectShowName: function(fieldMark,splitChar){
        return FieldUtil.getSelectShowName(fieldMark,splitChar);
    },
    /**
     * 获取浏览按钮字段对应的显示值
     */
    getBrowserShowName: function(fieldMark,splitChar){
        if(fieldMark.indexOf("field") === -1)
            return "";
        if(typeof splitChar === "undefined" || splitChar === "")
            splitChar = ",";
        let showname = "";
        const valueObj = this.getFieldValueObj(fieldMark);
        if(valueObj !== null && "specialobj" in valueObj){
            valueObj.specialobj && valueObj.specialobj.map((v,index) =>{
                if(index !== 0)
                    showname += splitChar;
                showname += v.name;
            });
        }
        return showname;
    },
    /**
     * 控制日期选择范围
     */
    controlDateRange: function(fieldMark, start, end){
        let startDate = null;
        let endDate = null;
        const reg = /^(-?\d+)(\.\d+)?$/;
        if (typeof start !== "undefined") {
            startDate = start.toString();
            if (reg.test(startDate))
                startDate = formatDate(new Date(new Date().getTime() + start * 24 * 60 * 60 * 1000),"yyyy-MM-dd")
        }
        if (typeof end !== "undefined") {
            endDate = end.toString();
            if (reg.test(endDate))
                endDate = formatDate(new Date(new Date().getTime() + end * 24 * 60 * 60 * 1000),"yyyy-MM-dd")
        }
        this.changeSingleField(fieldMark, {}, { startDate, endDate });
    },
    /**
     * 修改字段值，适用范围(单行文本、多行文本、选择框、浏览框、check框(0/1))
     * @params valueInfo(JSON)    非浏览框格式为：{value:"修改后的值"}，浏览按钮字段格式为：{value:"1,2,3",specialobj:[{id:"1",name:"张三"},{id:"2",name:"李四"},{id:"3",name:"王五"}...]}
     */
    changeFieldValue: function(fieldMark, valueInfo){
        this.changeSingleField(fieldMark, valueInfo, null)
    },
    /**
     * 修改字段只读/可编辑/必填/隐藏属性，此接口优先级低于标准功能显示属性联动(即设置了显示属性联动的可能覆盖此设置)
     * @params viewAttr(int)  1(变更为只读)/2(变更为可编辑)/3(变更为必填)/4(字段标签及名称都隐藏，同时不校验必填)
     */
    changeFieldAttr: function(fieldMark, viewAttr){
        viewAttr = parseInt(viewAttr);
        let fieldVars = {};
        let changeVars = {};
        //显示属性联动隐藏不能存fieldObj对象中，优化性能
        if(viewAttr === 4 || viewAttr === 5){
            fieldVars[fieldMark] = {viewAttr: -1};
            changeVars[`${fieldMark}_viewAttr`] = viewAttr;
        }else{
            fieldVars[fieldMark] = {viewAttr};
            changeVars[`${fieldMark}_viewAttr`] = -1;
        }
        this.changeMoreField({}, fieldVars);
        src.layoutStore.batchControlVariableMap(changeVars);
    },
    /**
     * 修改单个字段属性，修改值同时修改显示属性
     * @params valueInfo(obj) 可为空，变更的字段值
     */
    changeSingleField: function(fieldMark, valueInfo={}, variableInfo={}){
        const changeDatas = {};
        if(!_.isEmpty(valueInfo))
            changeDatas[fieldMark] = valueInfo;
        const fieldVars = {};
        if(!_.isEmpty(variableInfo)){
            if("viewAttr" in variableInfo){     //单独处理viewAttr的变更
                this.changeFieldAttr(fieldMark, variableInfo["viewAttr"]);
                delete variableInfo["viewAttr"];
            }
            fieldVars[fieldMark] = variableInfo;
        }
        this.changeMoreField(changeDatas, fieldVars);
    },
    /**
     * 批量修改多个字段值及属性
     * @params changeDatas(obj)  格式{field110:{value:"11"},field111_1:{value:"22"}
     * @params fieldVars(obj) 格式{field110:{viewAttr:1},field111_1:{viewAttr:3}}
     */
    changeMoreField: function(changeDatas={}, fieldVars={}){
        const { changeMoreFieldData } = src.layoutStore;
        const stepid = AI.generateStepId(AI.TYPE_WFFORM_API);
        changeMoreFieldData(changeDatas, fieldVars, stepid);
    },
    /**
     * 触发指定字段涉及的所有联动
     */
    triggerFieldAllLinkage: function(fieldMark){
        if(fieldMark.indexOf("field") === -1)
            return null;
        const { triggerAllLinkage,fieldAttrMap } = src.layoutStore;
        const index = fieldMark.indexOf("_");
        const fieldid = index>-1 ? fieldMark.substring(5, index) : fieldMark.substring(5);
        const rowIndex = index>-1 ? fieldMark.substring(index+1) : -1;
        const fieldAttr = fieldAttrMap.has(fieldid) ? fieldAttrMap.get(fieldid) : {};
        triggerAllLinkage(1, fieldAttr.tableMark, fieldid, rowIndex);
        //同时触发开发代码绑定的监听函数(新版公式运算)
        this.triggerFieldBindEvent(fieldMark, this.getFieldValue(fieldMark));
    },
    /**
     * 移除选择框字段选项(多次调用追加方式)
     */
    removeSelectOption: function(fieldMark, optionKeys){
        const fieldObj = this.getFieldObj(fieldMark);
        const { variable } = fieldObj;
        let filterOptionRange = variable.has("filterOptionRange") ? variable.get("filterOptionRange") : [];
        filterOptionRange = filterOptionRange.concat(optionKeys.split(","));
        this.changeSingleField(fieldMark, null, {filterOptionRange: filterOptionRange});
    },
    /**
     * 控制选择框字段选项范围
     */
    controlSelectOption: function(fieldMark, optionKeys){
        this.changeSingleField(fieldMark, null, {optionRange: optionKeys.split(","), filterOptionRange:null});
    },
    /**
     * 添加明细行
     * @params detailMark(String) 明细表标示，明细1就是detail_1，以此递增类推
     * @params initAddRowData(JSON) 新增行设置的初始值，可不传；格式为{field110:{value:"11"},field112:{value:"22"},...},注意key不带下划线标示
     */
    addDetailRow: function(detailMark, initAddRowData={}){
        DetailUtil.addRow(detailMark, initAddRowData);
    },
    /**
     * 删除明细行,没有提示删除的确认框(会清空明细已选情况)
     * @params detailMark(String) 明细表标示，明细1就是detail_1，以此递增类推
     * @params rowIndexMark(String) 明细行标示，全部选中:all,选中部分："1，2，3"
     */
    delDetailRow: function(detailMark, rowIndexMark){
        if(rowIndexMark === "all")
            rowIndexMark = this.getDetailAllRowIndexStr(detailMark);
        DetailUtil.setAllRowChecked(detailMark, false);
        if(rowIndexMark !== "")
            DetailUtil.delAssignRow(detailMark, rowIndexMark.split(","));
    },
    /**
     * 选中明细行
     * @params detailMark(String) 明细表标示，明细1就是detail_1，以此递增类推
     * @params rowIndexMark(String) 明细行标示，全部选中:all,选中部分："1，2，3"
     * @params needClearBeforeChecked(Boolean) 是否需要清除已有选中，默认为false
     */
    checkDetailRow: function(detailMark, rowIndexMark, needClearBeforeChecked){
        if(rowIndexMark === "all")
            rowIndexMark = this.getDetailAllRowIndexStr(detailMark);
        if(needClearBeforeChecked === true) //清除已选
            DetailUtil.setAllRowChecked(detailMark, false);
        DetailUtil.setRowChecked(detailMark, rowIndexMark, true);
    },
    /**
     * 控制明细数据行的显示及隐藏
     * @param detailMark(String) 明细表标示，明细1就是detail_1，以此递增类推
     * @param rowIndexMark(String) 明细行标示，全部行:all,部分行："1，2，3"
     * @param needHide 是否隐藏行，true:隐藏，false:显示
     */
    controlDetailRowDisplay: function(detailMark, rowIndexMark, needHide=true){
        if(rowIndexMark === "all")
            rowIndexMark = this.getDetailAllRowIndexStr(detailMark);
        let attr = {};
        rowIndexMark !== "" && rowIndexMark.split(",").map(rowIndex =>{
            attr[`row_${rowIndex}`] = { needHide };
        });
        const detailObj = DetailUtil.getDetailObj(detailMark);
        detailObj.controlDetailRowAttr(attr);
    },
    /**
     * 控制明细数据行check是否禁用勾选
     * @param detailMark(String) 明细表标示，明细1就是detail_1，以此递增类推
     * @param rowIndexMark(String) 明细行标示，全部行:all,部分行："1，2，3"
     * @param disableCheck 是否禁用勾选
     */
    controlDetailRowDisableCheck: function(detailMark, rowIndexMark, disableCheck=true){
        if(rowIndexMark === "all")
            rowIndexMark = this.getDetailAllRowIndexStr(detailMark);
        let attr = {};
        rowIndexMark !== "" && rowIndexMark.split(",").map(rowIndex =>{
            attr[`row_${rowIndex}`] = { disableCheck };
        });
        const detailObj = DetailUtil.getDetailObj(detailMark);
        detailObj.controlDetailRowAttr(attr);
    },
    /**
     * 获取明细所有行标示，逗号分隔
     * @params detailMark(String) 明细表标示，明细1就是detail_1，以此递增类推
     */
    getDetailAllRowIndexStr: function(detailMark){
        const detailObj = DetailUtil.getDetailObj(detailMark);
        return detailObj.allRowIndexStr;
    },
    //获取明细选中行下标，逗号分隔
    getDetailCheckedRowIndexStr: function(detailMark){
        const detailObj = DetailUtil.getDetailObj(detailMark);
        const checkRowArr = DetailUtil.getDetailCheckedRowArr(detailObj);
        return checkRowArr.join(",");
    },
    //获取明细行总数
    getDetailRowCount: function(detailMark){
        const allRowIndexStr = this.getDetailAllRowIndexStr(detailMark);
        return allRowIndexStr === "" ? 0 : allRowIndexStr.split(",").length;
    },
    //根据行号获取行序号
    getDetailRowSerailNum: function(mark, rowIndex=-1){
        const { fieldAttrMap,detailMap } = src.layoutStore;
        let detailMark = "";
        if(mark.startsWith("field") && mark.indexOf("_")>-1){
            const fieldid =  mark.substring(5,mark.indexOf("_"));
            detailMark = fieldAttrMap.has(fieldid) ? fieldAttrMap.get(fieldid).tableMark : "";
            rowIndex = mark.substring(mark.indexOf("_") + 1);
        }else if(mark.startsWith("detail_")){
            detailMark = mark;
        }
        let serialNum = -1;
        if(detailMark.indexOf("detail") === -1 || !detailMap.has(detailMark) || parseInt(rowIndex) < 0)
            return serialNum;
        const detailObj = DetailUtil.getDetailObj(detailMark);
        const { rowInfoArr } = detailObj;
        rowInfoArr && rowInfoArr.forEach(item =>{
            if(item.rowIndex === parseInt(rowIndex))
                serialNum = item.serialNum;
        });
        return serialNum;
    },
    //根据字段id获取对应的明细行数据库key值
    getDetailRowKey: function(fieldMark){
        if(fieldMark.indexOf("field") === -1 || fieldMark.indexOf("_") === -1)
            return -1;
        const fieldid = fieldMark.substring(5,fieldMark.indexOf("_"));
        const rowIndex = fieldMark.substring(fieldMark.indexOf("_") + 1);
        const { fieldAttrMap,detailMap } = src.layoutStore;
        const tableMark = fieldAttrMap.has(fieldid) ? fieldAttrMap.get(fieldid).tableMark : "";
        if(tableMark.indexOf("detail") === -1 || !detailMap.has(tableMark))
            return -1;
        const { rowInfo } = detailMap.get(tableMark);
        const rowAttr = rowInfo.has(`row_${rowIndex}`) ? rowInfo.get(`row_${rowIndex}`) : null;
        return rowAttr && rowAttr.has("keyid") ? parseInt(rowAttr.get("keyid")) : -1;
    },
    /**
     * 添加明细时默认复制最后一行记录
     * @params detailMark(String) 明细表标示，明细1就是detail_1，以此递增类推
     * @params needCopy(Boolean)  true需要复制，false取消复制
     */
    setDetailAddUseCopy: function (detailMark, needCopy) {
        if (detailMark.indexOf("detail_") === -1 || typeof needCopy !== "boolean")
            return;
        const detailObj = DetailUtil.getDetailObj(detailMark);
        detailObj.setAddDefaultCopy(needCopy);
    },
    /**
     * 文本字段可编辑状态，当值为空显示默认灰色提示信息，鼠标点击输入时消失
     */
    setTextFieldEmptyShowContent: function(fieldid, showContent){
        if(!fieldid || fieldid.indexOf("field") === -1)
            return;
        this.changeSingleField(fieldid, null, {emptyShowContent:showContent});
    },
    /**
     * 控制radio框字段打印时仅打印选中值名称
     */
    controlRadioPrintText: function(fieldid){
        src.layoutStore.batchControlVariableMap({[`radioPrintText_${fieldid}`]:true});
    },
    /**
     * 浏览按钮请求数据接口，支持传输自定义参数，联想输入及弹窗都支持
     */
    appendBrowserDataUrlParam: function(fieldMark, jsonParam){
        const fieldid = fieldMark.indexOf("_")>-1 ? fieldMark.substring(5,fieldMark.indexOf("_")) : fieldMark.substring(5);
        const fieldInfo = this.getFieldInfo(fieldid);
        if(fieldInfo && fieldInfo.htmltype === 3){  //限制浏览框类型
            this.changeSingleField(fieldMark, null, {customDataParam: jsonParam});
        }
    },
    /**
     * 复写浏览按钮属性
     */
    overrideBrowserProp: function(fieldMark, jsonParam){
        const fieldid = fieldMark.indexOf("_")>-1 ? fieldMark.substring(5,fieldMark.indexOf("_")) : fieldMark.substring(5);
        const fieldInfo = this.getFieldInfo(fieldid);
        if(fieldInfo && fieldInfo.htmltype === 3){  //限制浏览框类型
            this.changeSingleField(fieldMark, null, {customBrowserProp: jsonParam});
        }
    },
    /**
     * 扩展签字意见输入框底部按钮条
     */
    signBottomComps: [],
    appendSignEditorBottomBar: function(comps){
        this.signBottomComps = comps;
    },
    renderSignEditorBottomBar: function(bottomBarConfig=[]){
        this.signBottomComps && this.signBottomComps.map(item =>{
            bottomBarConfig.push({
                name: "Component",
                show: typeof item === "string" ? React.createElement("div", {dangerouslySetInnerHTML:{__html:item}}) : item
            });
        });
    },
    /**
     * 流程操作注册接口
     */
    OPER_SAVE: 'oper_save',         //保存
    OPER_SUBMIT: 'oper_submit',     //提交
    OPER_SUBMITCONFIRM: 'oper_submitconfirm',   //提交确认
    OPER_REJECT: 'oper_reject',     //退回
    OPER_REMARK: 'oper_remark',     //批注
    OPER_INTERVENE: 'oper_intervene',   //干预
    OPER_FORWARD: 'oper_forward',   //转发
    OPER_TURNHANDLE: 'oper_turnhandle', //转办
    OPER_ASKOPINION: 'oper_askopinion', //意见征询
    OPER_TAKFROWARD: 'oper_takforward',//征询转办
    OPER_TURNREAD: 'oper_turnread', //传阅
    OPER_TAKEBACK: 'oper_takeback', //强制收回
    OPER_DELETE: 'oper_delete', //删除
    OPER_ADDROW: 'oper_addrow', //添加明细行
    OPER_DELROW: 'oper_delrow', //删除明细行
    OPER_EDITDETAILROW: 'oper_editdetailrow',   //编辑明细行跳转(仅移动端)
    OPER_PRINTPREVIEW: 'oper_printpreview', //打印预览
    OPER_CLOSE: 'oper_close', //窗口关闭
    OPER_BEFOREVERIFY: 'oper_beforeverify', //校验必填前触发事件
    OPER_PRINT: 'oper_print',   //打印按钮事件
    OPER_BEFORECLICKBTN: 'oper_beforeClickBtn', //点右键按钮前置事件
    eventList: {},
    registerCheckEvent: function(types, fn){
        if(typeof(fn) !== "function")
            return;
        const arr = types.split(",");
        arr && arr.map(t =>{
            if(!(t in this.eventList))
                this.eventList[t] = new Array();
            this.eventList[t].push(fn);
        })
    },
    /**
     * @param type {onblur、onfocus、onclick、ondbclick、mouseover、mouseout}
     * 字段绑定公式触发动作事件
     */
    bindFieldAction: function(type, fieldids, fn){
        if(typeof(fn) !== "function")
            return;
        const reg = /^field\d+$/;
        const fieldArr = fieldids.split(",");
        fieldArr && fieldArr.map(fieldKey =>{
            if(reg.test(fieldKey)){
                this.registerAction(`${fieldKey}|${type}`, fn);
            }
        });
    },
    triggerFieldAction: function(type, fieldMark){
        if(!fieldMark || fieldMark.indexOf("field") !== 0)
            return;
        const index = fieldMark.indexOf("_");
        const fieldKey = index>0 ? fieldMark.substring(0,index) : fieldMark;
        const rowIndex = index>0 ? parseInt(fieldMark.substring(index+1)) : -1;
        this.triggerAction(`${fieldKey}|${type}`, [fieldKey, rowIndex]);
    },
    /**
     * 窗口滚动事件
     */
    bindScrollEvent: function(fn){
        this.registerAction(this.ACTION_SCROLL, fn);
    },
    triggerScrollEvent: function(){
        this.triggerAction(this.ACTION_SCROLL);
    },
    /**
     * 字段组件自定义渲染
     * 单行文本类型，支持代理渲染原字段组件
     * 所有表单字段，支持换行追加组件
     */
    proxyComps: {},
    afterComps: {},
    proxyFieldComp: function(fieldMark, el, range){
        this.customFieldComp(fieldMark, el, range, 1);
    },
    afterFieldComp: function(fieldMark, el, range){
        this.customFieldComp(fieldMark, el, range, 2);
    },
    customFieldComp: function(fieldMark, el, range, type){
        if(!fieldMark || fieldMark.indexOf("field") !== 0)
            return;
        const fieldid = fieldMark.indexOf("_")>-1 ? fieldMark.substring(5,fieldMark.indexOf("_")) : fieldMark.substring(5);
        const comp = typeof el === "string" ? React.createElement("div", {dangerouslySetInnerHTML:{__html:el}}) : el;
        const rangeArr = !!range ? range.split(",") : ["1","2","3"];
        if(type === 1){
            const fieldAttr = this.getFieldInfo(fieldid);
            if(fieldAttr.htmltype === 1 && fieldAttr.detailtype === 1){
                this.proxyComps[fieldMark] = {comp, rangeArr};
                this.forceRenderField(fieldMark);
            }
        }else if(type === 2){
            this.afterComps[fieldMark] = {comp, rangeArr};
            this.forceRenderField(fieldMark);
        }
    },
    forceRenderField: function(fieldMark){
        this.changeSingleField(fieldMark, {}, {forceRender: new Date().getTime()});
    },
    renderCustomComp: function(fieldMark, viewAttr, type, extendProps={}){
        const customComps = type === 1 ? this.proxyComps : this.afterComps;
        if(fieldMark in customComps){
            const customComp = customComps[fieldMark];
            const { comp,rangeArr } = customComp;
            if(_.indexOf(rangeArr,viewAttr.toString()) > -1){
                return type === 1 ? React.cloneElement(comp, {...extendProps}) : comp;
            }
        }
        return null;
    },
    /**
     * 代理组件渲染函数
     */
    proxyCompFn: {},
    proxyFieldContentComp: function(fieldid, fn){
        if(typeof fn === "function")
            this.proxyCompFn[`FieldContent_${fieldid}`] = fn;
    },
    // proxyCellTypeComp: function(cellClassName, fn){
    //     if(typeof fn === "function")
    //         this.proxyCompFn[`CellType_${cellClassName}`] = fn;
    // },
    getCustomProxyCompFn: function(key){
        return key in this.proxyCompFn ? this.proxyCompFn[key] : null;
    },
    /**
     * 钩子机制，指定动作触发注册函数
     */
    ACTION_ADDROW: "action_addrow_",
    ACTION_DELROW: "action_delrow_",
    ACTION_SCROLL: "action_scroll",
    ACTION_EDITDETAILROW: "action_editdetailrow",
    ACTION_SWITCHDETAILPAGING: "action_switchdetailpaging",
    ACTION_SWITCHTABLAYOUT: "action_switchtablayout",
    ACTION_TABCONFIG: "action_tabconfig",   //控制顶部标签项
    ACTION_SWITCHTAB: "action_switchtab",   //切换Tab后执行事件
    actionFnList: {},
    registerAction: function(key, fn){
        if(typeof(fn) !== "function")
            return;
        if(!(key in this.actionFnList) || !(this.actionFnList[key] instanceof Array))
            this.actionFnList[key] = new Array();
        this.actionFnList[key].push(fn);
        if(key === this.ACTION_TABCONFIG)
            src.globalStore.controlVariableMap("forceRenderReq", (src.globalStore.variableMap.get("forceRender") || 0)+1);
    },
    triggerAction: function(key, args=[], timeout=0){
        const fnAction = () =>{
            if(key.indexOf(this.ACTION_ADDROW) > -1){
                const detailIndex = parseInt(key.replace(this.ACTION_ADDROW, ""))-1;
                try{
                    eval("_customAddFun"+detailIndex+"("+args[0]+")");
                }catch(e){}
            }else if(key.indexOf(this.ACTION_DELROW) > -1){
                const detailIndex = parseInt(key.replace(this.ACTION_DELROW, ""))-1;
                try{
                    eval("_customDelFun"+detailIndex+"()");
                }catch(e){}
            }
            const fnArr = this.actionFnList[key] || []; 
            fnArr && fnArr.map(fn =>{
                try{
                    fn(...args);
                }catch(e){}
            });
        }
        timeout > 0 ? window.setTimeout(()=>{
            fnAction();
        },timeout) : fnAction();
    },
    overrideTabDatas: function(datas){
        const fnArr = this.actionFnList[this.ACTION_TABCONFIG] || [];
        let tabDatas = [...datas];
        fnArr.forEach(fn =>{
            try{
                tabDatas = fn(tabDatas);
            }catch(e){}
        });
        return tabDatas;
    }
}

export default WfForm_Public;